home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / lspsql2.zip / LISPSQL.C < prev    next >
C/C++ Source or Header  |  1993-02-19  |  75KB  |  1,807 lines

  1. /*****************************************************************************
  2.   Name: lispsql.c
  3.  
  4.   Description: Lisp - ASI-SQL interface. This programm gets parameters
  5.                from AutoLISP and pass them to ASI functions. Returned
  6.                values are passed to AutoLISP.
  7.  
  8.   Author: Frumkin Alexander
  9.           Autodesk, Inc.
  10.           St. Peterburg, Russia.
  11.           (812) 274-93-17
  12.  
  13.  ****************************************************************************
  14.  
  15.           lispsql.c
  16.           Copyright (C) 1991-1992 by Autodesk, Inc.
  17.  
  18.           Permission to use, copy, modify, and distribute this software 
  19.           for any purpose and without fee is hereby granted, provided 
  20.           that the above copyright notice appears in all copies and that 
  21.           both that copyright notice and this permission notice appear in 
  22.           all supporting documentation.
  23.  
  24.           THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED
  25.           WARRANTY.  ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR
  26.           PURPOSE AND OF MERCHANTABILITY ARE HEREBY DISCLAIMED.
  27.  *****************************************************************************
  28.  
  29.   Entry Points:
  30.  
  31.   Modification History:
  32.  
  33.   Bugs and restriction on use:
  34.  
  35.   Notes:
  36.  
  37. *****************************************************************************/
  38.  
  39. /****************************************************************************/
  40. /*  INCLUDES */
  41. /****************************************************************************/
  42. #include <stdio.h>
  43. #include <limits.h>
  44. #ifndef UNIX
  45. #include <stdlib.h>
  46. #endif  /* UNIX */
  47. #include <string.h>
  48. #include <adslib.h>
  49. #include "asi.h"
  50.  
  51. /****************************************************************************/
  52. /*   TYPEDEF */
  53. /****************************************************************************/
  54. typedef struct {                      /* function name-code struct */
  55.     char *cmdname;                    /* function name */
  56.     void (*cmdfunc)();                /* function registrated code */
  57. } CMD;
  58.  
  59. typedef struct {                      /* handle identifier struct */
  60.         ASIHANDLEPTR pt;              /* handle pointer */
  61.         short        NBh,             /* correspondent DBMS handle number */
  62.                      NCh;             /* correspondent CONNECTION handle
  63.                                          number */
  64. } HENDLID;
  65.  
  66. /****************************************************************************/
  67. /*   DEFINES */
  68. /****************************************************************************/
  69. #define S(x)                (x)->resval.rstring
  70. #define I(x)                (x)->resval.rint
  71. #define L(x)                (x)->resval.rlong
  72. #define EN(x)               (x)->resval.rlname
  73. #define R(x)                (x)->resval.rreal
  74. #define PT(x)               (x)->resval.rpoint
  75.  
  76. #define STEP                 20     /* step for glabal handle identifier 
  77.                                        array reallocation */ 
  78. #define DRV_H                0      /* DBMS handle flag */
  79. #define CON_H                1      /* CONNECTION handle flag */
  80. #define COM_H                2      /* COMMUNICATION handle flag */
  81. #define MAX_ACAD_PRINT       132    /* max length of string to be 
  82.                                        printed in AutoCAD */ 
  83. #define testHandlNumb(i)     ((i) >= 0 && (i) < n)
  84.                                     /* whether i is number of handle from
  85.                                        global array length n */ 
  86. #define ELEMENTS(x)          (sizeof(x)/sizeof(x[0]))
  87.                                     /* length of array */
  88.  
  89. /****************************************************************************/
  90. /*   FUNCTION PROTOTYPES */
  91. /****************************************************************************/
  92. void *allocMem              _((unsigned int, size_t));
  93. void *reallocMem            _((void *, size_t));
  94. int handlType               _((int));
  95. int eraseHandlId            _((short, int));
  96. void termAll                _((void));
  97. short searchDrvHandle       _((short));
  98. short putHandlId            _((short, short));
  99. short allocHandlid          _((void));
  100. short handlidNumb           _((void));
  101. struct resbuf *enttail      _((struct resbuf *));
  102. int     rbcmp               _((struct resbuf *, struct resbuf *));
  103. int     testHandle          _((short, int));
  104. struct resbuf *rbColDsc     _((short, short));
  105. int findName                _((short ,COLDSCPTR ,char *));
  106. struct resbuf *getVal       _((short, short));
  107. struct resbuf *getRowVal    _((short));
  108. void print_sql_err          _((char *, int));
  109. void lsp_initdrv            _((void));
  110. void lsp_termdrv            _((void));
  111. void lsp_termsql            _((void));
  112. void lsp_lon                _((void));
  113. void lsp_lof                _((void));
  114. void lsp_ohdl               _((void));
  115. void lsp_chdl               _((void));
  116. void lsp_com                _((void));
  117. void lsp_bnd                _((void));
  118. void lsp_exe                _((void));
  119. void lsp_cex                _((void));
  120. void lsp_ftr                _((void));
  121. void lsp_fbr                _((void));
  122. void lsp_fbk                _((void));
  123. void lsp_fet                _((void));
  124. void lsp_del                _((void));
  125. void lsp_upd                _((void));
  126. void lsp_currow             _((void));
  127. void lsp_rowqty             _((void));
  128. void lsp_cds                _((void));
  129. void lsp_colsdsc            _((void));
  130. void lsp_cmt                _((void));
  131. void lsp_rbk                _((void));
  132. void lsp_cvl                _((void));
  133. void lsp_stm                _((void));
  134. void lsp_opr                _((void));
  135. void lsp_err                _((void));
  136. void lsp_errmsg             _((void));
  137. void lsp_grow               _((void));
  138. void lsp_gettable           _((void));
  139.  
  140. /****************************************************************************/
  141. /*   GLOBAL VARIABLES */
  142. /****************************************************************************/
  143. HENDLID         *hid    = NULL;     /* global handle identifier array */
  144. short           n       = 0;        /* length of global handle array */
  145.  
  146. static CMD cmd[]    =   {{"ASI_INITDRV", lsp_initdrv},
  147.                          {"ASI_TERMDRV", lsp_termdrv},
  148.                          {"ASI_TERMSQL", lsp_termsql},
  149.                          {"ASI_LON", lsp_lon},
  150.                          {"ASI_LOF", lsp_lof},
  151.                          {"ASI_OHDL", lsp_ohdl},
  152.                          {"ASI_CHDL", lsp_chdl},
  153.                          {"ASI_COM", lsp_com},
  154.                          {"ASI_BND", lsp_bnd},
  155.                          {"ASI_EXE", lsp_exe},
  156.                          {"ASI_CEX", lsp_cex},
  157.                          {"ASI_FTR", lsp_ftr},
  158.                          {"ASI_FBR", lsp_fbr},
  159.                          {"ASI_FBK", lsp_fbk},
  160.                          {"ASI_FET", lsp_fet},
  161.                          {"ASI_DEL", lsp_del},
  162.                          {"ASI_UPD", lsp_upd},
  163.                          {"ASI_CURROW", lsp_currow},
  164.                          {"ASI_ROWQTY", lsp_rowqty},
  165.                          {"ASI_CDS", lsp_cds},
  166.                          {"ASI_COLSDSC", lsp_colsdsc},
  167.                          {"ASI_CMT", lsp_cmt},
  168.                          {"ASI_RBK", lsp_rbk},
  169.                          {"ASI_CVL", lsp_cvl},
  170.                          {"ASI_STM", lsp_stm},
  171.                          {"ASI_OPR", lsp_opr},
  172.                          {"ASI_ERR", lsp_err},
  173.                          {"ASI_ERRMSG", lsp_errmsg},
  174.                          {"ASI_GROW", lsp_grow},
  175.                          {"ASI_GETTABLE", lsp_gettable}};
  176.                                     /* global function-code array */
  177.  
  178. /****************************************************************************/
  179. /*.doc loadfuncs(internal)*/
  180. /*+
  181.     This function is called to load external functions into AutoLISP.
  182.     It will returns FALSE if any function cannot be defined.
  183. -*/
  184. /****************************************************************************/
  185. static int
  186. /*FCN*/loadfuncs()
  187. {
  188.     short i = ELEMENTS(cmd);        /* length of function-code array 'cmd' */
  189.  
  190.     while (i--)                     /* for every declared function from cmd */
  191.     if (ads_defun(cmd[i].cmdname, i) != RTNORM)
  192.             return FALSE;           /* wrong function defenition */
  193.  
  194.     return TRUE;                    /* all functions defined right */
  195.  
  196. }                                   /* end of loadfuncs () */
  197.  
  198. /****************************************************************************/
  199. /*.doc dofuncs(internal)*/
  200. /*+
  201.     This function is called to start external functions from AutoLISP.
  202. -*/
  203. /****************************************************************************/
  204. static int
  205. /*FCN*/dofuncs()
  206. {
  207.     short icommand = ads_getfuncode();
  208.                                     /* function code */
  209.  
  210.     if (icommand == RTERROR)        ads_abort ("fatal error");
  211.     (cmd[icommand].cmdfunc)();      /* executes function from cmd by code */
  212.     return TRUE;
  213.  
  214. }                                   /* end of dofuncs() */
  215.  
  216. /****************************************************************************/
  217. /*.doc main(external)*/
  218. /*+
  219.     Main entry point
  220. -*/
  221. /****************************************************************************/
  222. void
  223. /*FCN*/main(argc, argv)
  224.   int argc;                         /* argument count */
  225.   char *argv[];                     /* argument vector */
  226. {
  227.     short scode = RSRSLT;           /* return code */
  228.     int stat;                       /* work variable */
  229.  
  230.     ads_init(argc, argv);           /* Initializes interface between AutoLISP 
  231.                                        and this ADS application */ 
  232.  
  233.     for (;;) {
  234.         if ((stat = ads_link(scode)) < 0)   
  235.             return;                 /* wrong communication with AutoLISP */
  236.  
  237.         scode = RSRSLT;             /* default return code */
  238.  
  239.         switch (stat) {
  240.         case RQXLOAD:               /* load function by (xload) command */  
  241.             if ((scode = loadfuncs() ? RSRSLT : RSERR) == RSRSLT)
  242.                 asi_initsql();      /* SQL initialization */
  243.             break;
  244.  
  245.         case RQSUBR:                /* invoke function */
  246.             if (!dofuncs()) scode = RSERR;
  247.             break;
  248.  
  249.         case RQEND:                 /* terminate options */
  250.         case RQXUNLD:
  251.         case RQQUIT:
  252.             termAll();              /* free all handles */
  253.             asi_termsql();          /* term SQL */
  254.         }
  255.     }
  256. }                                   /* end of main () */
  257.  
  258. /****************************************************************************/
  259. /*.doc allocMem (internal)*/
  260. /*+
  261.     Memory allocation.
  262. -*/
  263. /****************************************************************************/
  264.  
  265. void
  266. /*FCN*/*allocMem (n, size)
  267.   unsigned int    n;                /* number of elements */
  268.   size_t          size;             /* size of element */
  269. {
  270.     void        *p;                 /* pointer to allocated memory */
  271.  
  272.     if ((p = calloc (n, size)) == NULL)     ads_abort ("Out of memory");
  273.  
  274.     return p;                       /* returns pointer to allocated memeory */
  275.  
  276. }                                   /* end of allocMem () */
  277.  
  278. /****************************************************************************/
  279. /*.doc reallocMem(internal) */
  280. /*+
  281.     Memory reallocation.
  282. -*/
  283. /****************************************************************************/
  284. void *
  285. /*FCN*/reallocMem (p, size)
  286.   void        *p;                   /* pointer to memory to be reallocated */
  287.   size_t      size;                 /* new size for reallocation */
  288. {
  289.     if ((p = realloc (p, size)) == NULL)    ads_abort ("Out of memory");
  290.  
  291.     return p;                       /* returns pointer to allocated memeory */
  292.  
  293. }                                   /* end of reallocMem () */
  294.  
  295. /****************************************************************************/
  296. /*.doc handlidNumb (internal) */
  297. /*+
  298.     Find new or use existing handler identifier number.
  299. -*/
  300. /****************************************************************************/
  301. short
  302. /*FCN*/handlidNumb ()
  303. {
  304.     short       i;                  /* work variable */                    
  305.  
  306.     /* 1. Check all allocated handle's identifiers for free handle in
  307.           'hid' array */
  308.     for (i = 0; i < n; i++)         
  309.     if (hid[i].pt == NULL)   break; /* free identifyer detected */
  310.  
  311.  
  312.     if (i == n)                    /* no free identifier detected */
  313.     /* 2. New handle identifier allocation */
  314.     i = allocHandlid();
  315.  
  316.     /* 3. New handle allocation for i-th identifier */
  317.     hid[i].pt = (ASIHANDLEPTR)allocMem (1, sizeof(ASIHANDLE));
  318.  
  319.     return i;                       /* returns number of identifier in
  320.                                        'hid' array */
  321.  
  322. }                                   /* end of handleidNumb () */
  323.  
  324. /****************************************************************************/
  325. /*.doc allocHandlid (internal) */
  326. /*+
  327.     Global array 'hid' memory manager.
  328. -*/
  329. /****************************************************************************/
  330. short
  331. /*FCN*/allocHandlid ()
  332. {
  333.     static short length;            /* current 'hid' length */
  334.  
  335.     if (n == 0) {                   /* first 'hid' allocation */
  336.         hid     = (HENDLID *)allocMem (STEP, sizeof(HENDLID));
  337.         length  = STEP;             /* length of array 'hid' */
  338.     }
  339.  
  340.     if (n == length) {              /* lenth is not enought */
  341.         if (length > SHRT_MAX - STEP)  ads_abort ("Out of memory");
  342.         length  += STEP;            /* new length of array 'hid' */
  343.         hid     = (HENDLID *)reallocMem (hid, 
  344.                         (unsigned int)(length*sizeof(HENDLID)));
  345.     }
  346.  
  347.     hid[n].pt = NULL;
  348.  
  349.     return n++;                     /* returns next element of 'hid' number */
  350.  
  351. }                                   /* end of allocHandlid () */
  352.  
  353. /****************************************************************************/
  354. /*.doc putHandlId(internal) */
  355. /*+
  356.     Puts handle identifier into global 'hid' array.
  357. -*/
  358. /****************************************************************************/
  359. short
  360. /*FCN*/putHandlId (NBase, NCon)
  361.   short        NBase,               /* DBMS handle number */
  362.                NCon;                /* CONNECTION handle number */
  363. {
  364.     short   i   = handlidNumb();    /* free handle identifier in 'hid'
  365.                                        number */
  366.  
  367.     hid[i].NCh  = NCon;             /* write connection handle number to
  368.                                        handle identifier */
  369.     hid[i].NBh  = (NCon == SHRT_MAX)/* write correspondent DBMS handle
  370.                                        number to identifier */
  371.                     ? NBase
  372.                     : hid[NCon].NBh;
  373.     return i;                       /* returns current handle identifer
  374.                                        number in 'hid' array */ 
  375. }                                   /* end of putHandleId () */
  376.  
  377. /****************************************************************************/
  378. /*.doc handlIType (internal) */
  379. /*+
  380.     Returns handl type.
  381. -*/
  382. /****************************************************************************/
  383. int
  384. /*FCN*/handlType (i)
  385.   int         i;                    /* handle identifier number in 'hid'
  386.                                        array */ 
  387. {
  388.     return (hid[i].NCh == SHRT_MAX) 
  389.             ? ((hid[i].NBh == SHRT_MAX) ? DRV_H : CON_H)
  390.             : COM_H;
  391. }
  392.  
  393. /****************************************************************************/
  394. /*.doc eraseHandlId (internal) */
  395. /*+
  396.     Free handle identifier and correspondent connection and communication
  397.     handles identifiers in 'hid' array.
  398. -*/
  399. /****************************************************************************/
  400.  
  401. int     eraseHandlId (i, type)
  402.   short             i;              /* handle number in 'hid' array */
  403.   int               type;           /* handle type */
  404. {
  405.     int             j,              /* work variables */
  406.                     ret = ASI_GOOD;
  407.     int             htype;
  408.  
  409.     if (!testHandlNumb(i))  {       /* check handle number */
  410.         ads_printf ("\nWrong handle number.");
  411.         return ASI_BAD;
  412.     }
  413.  
  414.     htype   = handlType(i);         /* check handle type */
  415.     if (htype != type) {
  416.         ads_printf ("\nWrong handle type.");
  417.         return ASI_BAD;
  418.     }
  419.  
  420.     if (type < COM_H)               /* whether there are correspondent
  421.                                        CONNECTION and/or COMMUNICATION
  422.                                        handles */
  423.     for (j = 0; j < n && ret == ASI_GOOD; j++) {
  424.                                     /* search in 'hid' array from
  425.                                        start to end exept current */
  426.         htype                           = SHRT_MAX;
  427.         if (hid[j].pt != NULL && j != i)
  428.         if (hid[j].NCh == i)            htype   = COM_H;
  429.         else if(hid[j].NBh == i)        htype   = CON_H;
  430.         if (htype != SHRT_MAX)      /* correspondent handle is found */
  431.             ret &= eraseHandlId (j, htype);
  432.     }
  433.  
  434.  
  435.     switch (type) {
  436.         case COM_H:                 /* closes communication handle */
  437.         ret &= asi_chdl (hid[i].pt);
  438.         break;
  439.  
  440.         case CON_H:                 /* logs off from data base */
  441.         ret &= asi_lof (hid[i].pt);
  442.         break;
  443.  
  444.         case DRV_H:
  445.         if (searchDrvHandle (i) == SHRT_MAX)
  446.                                     /* whether no more such DBMS handles
  447.                                        detected */
  448.         ret &= asi_termdrv (hid[i].pt);
  449.     }
  450.  
  451.     if (hid[i].pt != NULL) {        /* wheter current handle not free */
  452.         free(hid[i].pt);            /* free current handle */
  453.         hid[i].pt   = NULL;         /* set current handle structure pointer 
  454.                                        to NULL */
  455.     }
  456.  
  457.     return ret;                     /* returns error code */
  458. }                                   /* end of eraseHandleId () */
  459.  
  460. /****************************************************************************/
  461. /*.doc termAll (internal) */
  462. /*+
  463.     Terms all handles.
  464. -*/
  465. /****************************************************************************/
  466. void
  467. /*FCN*/termAll()
  468. {
  469.     short   i;                      /* work index */
  470.  
  471.     for (i = 0; i < n; i++)         /* loop by all DBMS handle from 'hid'
  472.                                        array */ 
  473.     if (hid[i].pt != NULL && handlType (i) == DRV_H)
  474.         eraseHandlId (i, DRV_H);    /* free DBMS handle and all correspondent
  475.                                        handles */
  476.  
  477.     if (hid != NULL)    free (hid); /* free lobal 'hid' array */
  478.     hid     = NULL;
  479.     n       = 0;
  480.  
  481. }                                   /* end of termAll() */
  482.  
  483. /****************************************************************************/
  484. /*.doc searchDrvHandle (internal) */
  485. /*+
  486.     Search DBMS handle with driver equal to current DBMS handle one.
  487. -*/
  488. /****************************************************************************/
  489. short
  490. /*FCN*/searchDrvHandle (current)
  491. short               current;        /* current handle number in 'hid' array */
  492. {
  493.     short           i;              /* work index */
  494.  
  495.     for (i = 0; i < n; i++)         /* for all handle identifiers in 'hid' */
  496.     if (i != current && 
  497.         hid[i].pt->drv_id == hid[current].pt->drv_id) 
  498.         break;                    /* there is any such handle */
  499.  
  500.     return i < n                  /* returns */
  501.         ? i                       /* number of such handle */  
  502.         : SHRT_MAX;
  503. }                                 /* end of searchDrvHandle () */
  504.  
  505. /****************************************************************************/
  506. /*.doc enttail (internal) */
  507. /*+
  508.     Search an tail of entity buffer.
  509. -*/
  510. /****************************************************************************/
  511. struct resbuf *
  512. /*FCN*/enttail (rchain)
  513.   struct resbuf   *rchain;          /* pointer to current result buffer */
  514. {
  515.     while (rchain->rbnext != NULL)  /* go by buffer step by step */
  516.     rchain = rchain->rbnext;
  517.  
  518.     return rchain;                  /* returns pointer to last group */
  519. }                                   /* end of enttail() */
  520.  
  521. /****************************************************************************/
  522. /*.doc rbColDsc (internal) */
  523. /*+
  524.     Builds column description result buffer.
  525. -*/
  526. /****************************************************************************/
  527. struct resbuf *
  528. /*FCN*/rbColDsc (nhandl, ncol)
  529.   short             nhandl,         /* COMMUNICATION handle humber */
  530.                     ncol;           /* column number */
  531. {
  532.     COLDSC          cd;             /* column description structure */
  533.     struct resbuf   *rb = NULL;     /* work result buffer */
  534.  
  535.     if (asi_cds (hid[nhandl].pt, (int)ncol, &cd) == ASI_GOOD) {
  536.                                     /* gets column description */
  537.         rb = ads_buildlist (RTSTR, cd.colname,
  538.                             RTSHORT, cd.precision,
  539.                             RTSHORT, cd.scale,
  540.                             NULL);
  541.     }
  542.  
  543.     return rb;                      /* returns column description result 
  544.                                        buffer */
  545.  
  546. }                                   /* end of rbColDsc () */
  547.  
  548. /****************************************************************************/
  549. /*.doc findName(internal) */
  550. /*+
  551.     Search column by defined name.
  552. -*/
  553. /****************************************************************************/
  554. int
  555. /*FCN*/findName ( Hnumb, cd, Name)
  556.   short           Hnumb;            /* COMMUNICATION handle humber */
  557.   COLDSCPTR       cd;               /* column description */
  558.   char            *Name;            /* column name */
  559. {
  560.     int         flag = FALSE,       /* find flag (off by default) */
  561.                 i;                  /* work index */
  562.  
  563.     for (i = 0; asi_cds (hid[Hnumb].pt, (int)i, cd) == ASI_GOOD; i++)
  564.                                     /* loop by all columns */
  565.     if (!stricmp (Name, cd->colname)) {
  566.                                     /* names are equal */
  567.         flag = TRUE;                /* flag on */
  568.         break;                      /* stop search */
  569.     }
  570.  
  571.     return flag;                    /* returns find flag */
  572.  
  573. }                                   /* end of findName () */
  574.  
  575. /****************************************************************************/
  576. /*.doc rbcmp (internal) */
  577. /*+
  578.     Compares result buffers for length and types.
  579. -*/
  580. /****************************************************************************/
  581. int
  582. /*FCN*/rbcmp (rb, shab)
  583.   struct resbuf   *rb,              /* result buffer to be checked */
  584.                   *shab;            /* result buffer to be compared with */
  585. {
  586.     int         flag = TRUE;        /* continue flag */
  587.  
  588.     while (flag && shab != NULL)    /* loop by both buffers */
  589.     if (rb == NULL &&               /* end of checked buffer */
  590.         ads_printf ("\nerror: too few arguments.") == RTNORM ||
  591.         rb->restype != shab->restype &&
  592.                                     /* types mismatch */
  593.         ads_printf ("\nerror: bad argument type.")== RTNORM)
  594.         flag    = FALSE;            /* continue flag off */
  595.     else {                          /* go to next groups */
  596.         rb      = rb->rbnext;
  597.         shab    = shab->rbnext;
  598.     }
  599.  
  600.     if (flag && rb != NULL) {       /* end of second buffer */
  601.         ads_printf ("\nerror: too many arguments.");
  602.         flag = FALSE;
  603.     }
  604.     if (shab != NULL)       ads_relrb(shab);
  605.  
  606.     return flag;                    
  607. }                                   /* end of rbcmp () */
  608.  
  609. /****************************************************************************/
  610. /*.doc testHandle (internal) */
  611. /*+
  612.     Checks handle identifier in 'hid' array by number and type.
  613. -*/
  614. /****************************************************************************/
  615. int
  616. /*FCN*/testHandle (Numb, type)
  617.   short       Numb;                 /* handle identifier number */
  618.   int         type;                 /* handle type */
  619. {
  620.     int     ret = FALSE;            /* returns code (FALSE by default) */
  621.  
  622.     if (!testHandlNumb(Numb))       /*  check handle number  */
  623.         ads_prompt ("\nerror: bad handle.");
  624.     else if (handlType (Numb) != type)
  625.                                     /* check handle type */
  626.         ads_prompt ("\nerror: wrong handle type.");
  627.     else ret = TRUE;
  628.  
  629.     return ret;
  630.  
  631. }                                   /* end of testHandle () */
  632.  
  633. /****************************************************************************/
  634. /*.doc getVal (internal) */
  635. /*+
  636.     Returns value from Ncol column and current row as result buffer.
  637. -*/
  638. /****************************************************************************/
  639. struct resbuf *
  640. /*FCN*/getVal(Nhandle, NCol)
  641.   short               Nhandle,      /* COMMUNICATION handle number */
  642.                       NCol;         /* column number */
  643. {
  644.     struct resbuf   *rb = NULL;     /* work buffer */
  645.     COLDSC          cd;             /* column description */
  646.     int             type;           /* work variables */
  647.     char            buff[256];
  648.  
  649.     if (asi_cds (hid[Nhandle].pt, (int)NCol, &cd) == ASI_GOOD &&
  650.                                     /* gets column description */
  651.         asi_cvl (hid[Nhandle].pt, (int)NCol, buff, cd.precision, &type)
  652.         == ASI_GOOD)                /* gets column value */
  653.         switch (type) {
  654.         case ASI_SCHAR:             /* string value */
  655.             buff[cd.precision] = '\0';
  656.             rb = ads_buildlist (RTSTR, buff, NULL);
  657.             break;
  658.  
  659.         case ASI_SNULL:             /* empty value */
  660.             rb = ads_buildlist (RTSTR, "", NULL);
  661.             break;
  662.  
  663.         case ASI_SINT:              /* integer value */
  664.             rb = ads_buildlist(RTLONG, *(int *)buff, NULL);
  665.             break;
  666.  
  667.         case ASI_SREAL:             /* float value */
  668.             rb = ads_buildlist(RTREAL, *(ads_real *)buff, NULL);
  669.         }
  670.  
  671.     return rb;                      /* returns value as result buffer */
  672.  
  673. }                                   /* end of getVal () */
  674.  
  675. /****************************************************************************/
  676. /*.doc getRowVal (internal) */
  677. /*+
  678.     Gets values from current row as result buffer.
  679. -*/
  680. /****************************************************************************/
  681. struct resbuf *
  682. /*FCN*/getRowVal (Nhandle)
  683.   short             Nhandle;        /* COMMUNICATION handle number in 'hid'
  684.                                        array */
  685. {
  686.     struct resbuf   *root = NULL,   /* work pointers */
  687.                     *rb;
  688.     short           i;              /* work index */
  689.  
  690.     for (root = NULL, i = 0; (rb = getVal(Nhandle, i)) != NULL; i++)
  691.                                     /* loop by all columns */
  692.         if (i == 0)     root = rb;  /* first column */
  693.         else            enttail(root)->rbnext = rb;
  694.                                     /* next column */
  695.     return root;                    /* returns pointer to first group */
  696.  
  697. }                                   /* end of getRowVal () */
  698.  
  699. /****************************************************************************/
  700. /*.doc print_sql_err(internal) */
  701. /*+
  702.     Prints SQL statement and marcs error.
  703. -*/
  704. /****************************************************************************/
  705. void print_sql_err (str, pos)
  706.   char        *str;                 /* SQL statement */
  707.   int         pos;                  /* error position */
  708. {
  709.     char    c   = '\0';             /* work variable */
  710.     int     l   = (int)strlen (str);/* work variable */
  711.  
  712.     str[pos]    = ' ';              /* put ' ' to error position */
  713.  
  714.     while (l > 0) {                 /* devide str by parts of
  715.                                        length MAX_ACAD_PRINT */
  716.         if (l > MAX_ACAD_PRINT)  {  /* string is longer then MAX_ACAD_PRINT */
  717.             c                   = str[MAX_ACAD_PRINT];
  718.                                     /* csore symbol at MAX_ACAD_PRINT
  719.                                        position in 'c' */
  720.             str[MAX_ACAD_PRINT] = '\0';
  721.                                     /* put end_of_line symbol to
  722.                                        MAX_ACAD_PRINT position */
  723.         }
  724.         ads_printf ("%s", str);     /* prints part of str */
  725.         l -= MAX_ACAD_PRINT;        /* recalculate length of unprinted part */
  726.         str += MAX_ACAD_PRINT;      /* recalculate start of unprinted part */
  727.         if (l > 0)              *str = c;
  728.                                     /* put 'c' instead of end_of_file symbol */
  729.     }
  730. }                                   /* end of print_sql_err () */ 
  731.  
  732. /****************************************************************************/
  733. /*.doc lsp_initdrv (external) */
  734. /*+
  735.     Driver initialization.
  736. -*/
  737. /****************************************************************************/
  738. void
  739. /*FCN*/lsp_initdrv ()
  740. {
  741.     short         i;                /* work variable */
  742.     struct resbuf *rb,              /* result buffer to get input from
  743.                                        AutoLISP */  
  744.                   *rb1;             /* result buffer to compare input */
  745.  
  746.     rb = ads_getargs();             /* gets arguments from AutoLISP
  747.                                        as result buffer */
  748.     rb1 = ads_newrb (RTSTR);        /* for driver name */
  749.  
  750.     ads_retnil();                   /* returns nil to AutoLISP by default */
  751.     if (rbcmp (rb, rb1)) {          /* wheter arguments are right */
  752.         i = putHandlId (SHRT_MAX, SHRT_MAX);
  753.                                     /* put new DBMS handle to 'hid' */
  754.         if (asi_initdrv (hid[i].pt, S(rb)) == ASI_GOOD)
  755.                                     /* driver initialization */
  756.             ads_retint(i);          /* returns handle number to AutoLISP */
  757.     } 
  758. }                                   /* end of lsp_initdrv () */
  759.  
  760. /****************************************************************************/
  761. /*.doc lsp_termdrv (external) */
  762. /*+
  763.     Terminate driver and free all correspondent CONNECTION and
  764.     COMMUNICATION drivers.
  765. -*/
  766. /****************************************************************************/
  767. void
  768. /*FCN*/lsp_termdrv ()
  769. {
  770.     struct resbuf *rb,              /* result buffer to get input from
  771.                                        AutoLISP */  
  772.                   *rb1;             /* result buffer to compare input */
  773.  
  774.     rb = ads_getargs();             /* gets arguments from AutoLISP
  775.                                        as result buffer */
  776.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  777.  
  778.     if (rbcmp (rb ,rb1) &&          /* wheter arguments are right */
  779.         testHandle (I(rb), DRV_H) &&/* whether handle number is right */
  780.         eraseHandlId (I(rb), DRV_H) == ASI_GOOD)
  781.                                     /* whether free successfull */
  782.         ads_retint(1);              /* returns TRUE to AutoLISP */
  783.     else   ads_retnil();            /* returns nil to AutoLISP */
  784.  
  785. }                                   /* end of lsp_termdrv () */
  786.  
  787. /****************************************************************************/
  788. /*.doc lsp_termsql (external) */
  789. /*+
  790.     Term SQL and free all handles.
  791. -*/
  792. /****************************************************************************/
  793. void
  794. /*FCN*/lsp_termsql ()
  795. {
  796.     struct resbuf *rb;              /* result buffer to get input from
  797.                                        AutoLISP */  
  798.  
  799.     rb = ads_getargs();             /* gets arguments from AutoLISP
  800.                                        as result buffer */
  801.  
  802.     ads_retnil();                   /* returns nil to AutoLISP by default */
  803.     if (rbcmp (rb, NULL)) {         /* wheter arguments are right */
  804.         termAll();                  /* free all handles and 'hid' array */
  805.         if (asi_termsql () == ASI_GOOD) 
  806.                                     /* whether term successfull */
  807.         ads_retint(1);              /* returns TRUE to AutoLISP */
  808.     }
  809. }                                   /* end of lsp_termsql () */
  810.  
  811. /****************************************************************************/
  812. /*.doc lsp_lon (external) */
  813. /*+
  814.     Logon to data base.
  815. -*/
  816. /****************************************************************************/
  817. void
  818. /*FCN*/lsp_lon ()
  819. {
  820.     short         i;                /* work variable */
  821.     struct resbuf *rb,              /* result buffer to get input from
  822.                                        AutoLISP */  
  823.                   *rb1;             /* result buffer to compare input */
  824.  
  825.     rb = ads_getargs();             /* gets arguments from AutoLISP
  826.                                        as result buffer */
  827.     rb1 = ads_buildlist(RTSHORT, 0, /* for handle number */
  828.                         RTSTR, "",  /* for table name */
  829.                         RTSTR, "",  /* for user name */
  830.                         RTSTR, "",  /* for password */
  831.                         NULL);
  832.  
  833.     ads_retnil();                   /* returns nil to AutoLISP by default */
  834.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  835.         testHandle (I(rb), DRV_H)) {/* whether handle number is right */
  836.         i = putHandlId (I(rb), SHRT_MAX);
  837.                                     /* put new DBMS handle to 'hid' */
  838.         if (asi_lon (hid[i].pt, hid[I(rb)].pt, S(rb->rbnext),
  839.                      S(rb->rbnext->rbnext),
  840.                      S(rb->rbnext->rbnext->rbnext)) == ASI_GOOD)
  841.                                     /* lof on successful */
  842.             ads_retint (i);         /* returns handle number to AutoLISP */
  843.         else {                      /* logon to data base failed */
  844.             free (hid[i].pt);       /* free new handle in 'hid' */
  845.             hid[i].pt = NULL;
  846.         }
  847.     }
  848. }                                   /* end of lsp_lon () */
  849.  
  850. /****************************************************************************/
  851. /*.doc lsp_lof (external) */
  852. /*+
  853.     Log off from data base.
  854. -*/
  855.  
  856. /****************************************************************************/
  857. void
  858. /*FCN*/lsp_lof ()
  859. {
  860.     struct resbuf *rb,              /* result buffer to get input from
  861.                                        AutoLISP */  
  862.                   *rb1;             /* result buffer to compare input */
  863.  
  864.     rb = ads_getargs();             /* gets arguments from AutoLISP
  865.                                        as result buffer */
  866.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  867.  
  868.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  869.         testHandle (I(rb), CON_H) &&/* whether handle number is right */
  870.         eraseHandlId (I(rb), CON_H) == ASI_GOOD)
  871.                                     /* whether free succsessfull */
  872.         ads_retint(1);              /* returns TRUE to AutoLISP */
  873.     else   ads_retnil();            /* returns nil to AutoLISP */
  874.  
  875. }                                   /* end of lsp_lof () */
  876.  
  877. /****************************************************************************/
  878. /*.doc lsp_ohdl (external) */
  879. /*+
  880.     Open COMMUNICATION handle.
  881. -*/
  882. /****************************************************************************/
  883. void
  884. /*FCN*/lsp_ohdl ()
  885. {
  886.     short         i;                /* work variable */
  887.     struct resbuf *rb,              /* result buffer to get input from
  888.                                        AutoLISP */  
  889.                   *rb1;             /* result buffer to compare input */
  890.  
  891.     rb = ads_getargs();             /* gets arguments from AutoLISP
  892.                                        as result buffer */
  893.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  894.  
  895.     ads_retnil();                   /* returns nil to AutoLISP by default */
  896.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  897.         testHandle(I(rb), CON_H)) { /* whether handle number is right */
  898.         i = putHandlId (SHRT_MAX, I(rb));
  899.                                     /* put new COMMUNICATION handle to 'hid' */
  900.         if (asi_ohdl (hid[i].pt, hid[I(rb)].pt) == ASI_GOOD)
  901.             ads_retint (i);         /* returns handle number to AutoLISP */
  902.         else  {                     /* open handle failed */
  903.             free(hid[i].pt);        /* free new handle in 'hid' */
  904.             hid[i].pt = NULL;
  905.         }
  906.     }
  907. }                                   /* end of lsp_ohdl () */
  908.  
  909. /****************************************************************************/
  910. /*.doc lsp_chdl (external) */
  911. /*+
  912.     Close COMMUNICATION handle and free handle in 'hid' array.
  913. -*/
  914. /****************************************************************************/
  915. void
  916. /*FCN*/lsp_chdl ()
  917. {
  918.     struct resbuf *rb,              /* result buffer to get input from
  919.                                        AutoLISP */  
  920.                   *rb1;             /* result buffer to compare input */
  921.  
  922.     rb = ads_getargs();             /* gets arguments from AutoLISP
  923.                                        as result buffer */
  924.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  925.  
  926.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  927.         testHandle(I(rb), COM_H) && /* whether handle number is right */
  928.         eraseHandlId (I(rb), COM_H) == ASI_GOOD)
  929.                                     /* whether free successful */
  930.         ads_retint(1);              /* returns TRUE to AutoLISP */
  931.     else   ads_retnil();            /* returns nil to AutoLISP */
  932.  
  933. }                                   /* end of lsp_chdl () */
  934.  
  935.  
  936. /****************************************************************************/
  937. /*.doc lsp_com (external) */
  938. /*+
  939.     Compiles SQL statement.
  940. -*/
  941. /****************************************************************************/
  942. void
  943. /*FCN*/lsp_com ()
  944. {
  945.     struct resbuf *rb,              /* result buffer to get input from
  946.                                        AutoLISP */  
  947.                   *rb1;             /* result buffer to compare input */
  948.  
  949.     rb = ads_getargs();             /* gets arguments from AutoLISP
  950.                                        as result buffer */
  951.     rb1 = ads_buildlist(RTSHORT, 0, /* for handle number */
  952.                         RTSTR, "",  /* for SQL statement */
  953.                         NULL);
  954.  
  955.     ads_retnil();                   /* returns nil to AutoLISP by default */
  956.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  957.         testHandle(I(rb), COM_H))   /* whether handle number is right */
  958.     if (asi_com (hid[I(rb)].pt, S(rb->rbnext)) == ASI_BAD) {
  959.                                     /* compilation failed */
  960.         ads_prompt ("\n");
  961.         print_sql_err (S(rb->rbnext),asi_synerrpos(hid[I(rb)].pt));
  962.                                     /* prints statement with arrow symbol
  963.                                        att error position */
  964.         ads_printf ("\n%s", asi_errmsg(hid[I(rb)].pt));
  965.                                     /* prints error message */
  966.     }  else ads_retint(1);          /* returns TRUE to AutoLISP */
  967.  
  968. }                                   /* end of lsp_com () */
  969.  
  970.  
  971. /****************************************************************************/
  972. /*.doc lsp_bnd (external) */
  973. /*+
  974.     Binds host variable into the SQL statement.
  975. -*/
  976. /****************************************************************************/
  977. void
  978. /*FCN*/lsp_bnd ()
  979. {
  980.     int             ret = ASI_BAD;  /*return code (ASI_BAD by default) */
  981.     ads_real        rbuff;          /* work buffer */
  982.     integer         ibuff;          /* work buffer */
  983.     long            lbuff;          /* work buffer */
  984.     struct resbuf   *rb,            /* result buffer to input from
  985.                                        AutoLISP */
  986.                     *rb1;           /* result buffer to compare input */
  987.  
  988.  
  989.     rb  = ads_getargs();            /* gets arguments from AutoLISP
  990.                                        as result buffer */
  991.     rb1 = ads_buildlist(RTSHORT, 0, /* for handle number */
  992.                         RTSTR, "",  /* for host variable name */
  993.                         RTSTR, "",  /* for value to be bind or '\0' for
  994.                                        empty value */
  995.                         RTSTR, "",  /* for value type */
  996.                         RTSHORT, 0, /* for length */
  997.                         NULL);
  998.  
  999.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1000.         testHandle (I(rb), COM_H))  /* whether handle number is right */
  1001.  
  1002.     if (*S(rb->rbnext->rbnext) == '\0')
  1003.                                     /* empty value */
  1004.         ret = asi_bnd(hid[I(rb)].pt, S(rb->rbnext), NULL,
  1005.                       I(rb->rbnext->rbnext->rbnext->rbnext), 0);
  1006.     else if (!stricmp(S(rb->rbnext->rbnext->rbnext), "asi_hchar"))
  1007.                                     /* string value */
  1008.         ret = asi_bnd(hid[I(rb)].pt, S(rb->rbnext), S(rb->rbnext->rbnext),
  1009.                       I(rb->rbnext->rbnext->rbnext->rbnext), ASI_HCHAR);
  1010.     else if (!stricmp(S(rb->rbnext->rbnext->rbnext), "asi_hint")) {
  1011.                                     /* integer value */
  1012.         ibuff = atoi(S(rb->rbnext->rbnext));
  1013.         ret = asi_bnd(hid[I(rb)].pt, S(rb->rbnext), &ibuff,
  1014.                       I(rb->rbnext->rbnext->rbnext->rbnext), ASI_HINT);
  1015.     } else if (!stricmp(S(rb->rbnext->rbnext->rbnext), "asi_hshort")) {
  1016.                                     /* short value */
  1017.         ibuff = atoi(S(rb->rbnext->rbnext));
  1018.         ret = asi_bnd(hid[I(rb)].pt, S(rb->rbnext), &ibuff,
  1019.                       I(rb->rbnext->rbnext->rbnext->rbnext), ASI_HSHORT);
  1020.     } else if (!stricmp(S(rb->rbnext->rbnext->rbnext), "asi_hlong")) {
  1021.                                     /* long value */
  1022.         lbuff = (long)atoi(S(rb->rbnext->rbnext));
  1023.         ret = asi_bnd(hid[I(rb)].pt, S(rb->rbnext), &lbuff,
  1024.                       I(rb->rbnext->rbnext->rbnext->rbnext), ASI_HLONG);
  1025.     } else if (!stricmp(S(rb->rbnext->rbnext->rbnext), "asi_hreal")) {
  1026.                                     /* real value */
  1027.         rbuff = atof(S(rb->rbnext->rbnext));
  1028.         ret = asi_bnd(hid[I(rb)].pt, S(rb->rbnext), &rbuff,
  1029.                       I(rb->rbnext->rbnext->rbnext->rbnext), ASI_HREAL);
  1030.     } else if (!stricmp(S(rb->rbnext->rbnext->rbnext), "asi_hfloat")) {
  1031.                                     /* float value */
  1032.         rbuff = atof(S(rb->rbnext->rbnext));
  1033.         ret = asi_bnd(hid[I(rb)].pt, S(rb->rbnext), &rbuff,
  1034.                       I(rb->rbnext->rbnext->rbnext->rbnext), ASI_HFLOAT);
  1035.     }
  1036.  
  1037.     if (ret == ASI_GOOD)            /* whether bind successful */
  1038.         ads_retint(1);              /* returns TRUE to AutoLISP */
  1039.     else                            /* bind failed */
  1040.         ads_retnil();               /* returns nil to AutoLISP */
  1041.  
  1042. }                                   /*  end of lsp_bnd () */
  1043.  
  1044. /****************************************************************************/
  1045. /*.doc lsp_exe (external) */
  1046. /*+
  1047.     Executes compiled SQL statement.
  1048. -*/
  1049. /****************************************************************************/
  1050.  
  1051. void lsp_exe ()
  1052. {
  1053.     struct resbuf *rb,              /* result buffer to get input from
  1054.                                        AutoLISP */  
  1055.                   *rb1;             /* result buffer to compare input */
  1056.  
  1057.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1058.                                        as result buffer */
  1059.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1060.  
  1061.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1062.         testHandle (I(rb), COM_H) &&/* whether handle number is right */
  1063.         asi_exe (hid[I(rb)].pt) == ASI_GOOD)
  1064.                                     /* whether compilation successful */
  1065.         ads_retint(1);              /* returns TRUE to AutoLISP */
  1066.     else
  1067.         ads_retnil();               /* returns nil to AutoLISP */
  1068.  
  1069. }                                   /* end of lsp_exe () */
  1070.  
  1071. /****************************************************************************/
  1072. /*.doc lsp_cex (external) */
  1073. /*+
  1074.     Compiles and executes SQL statement.
  1075. -*/
  1076. /****************************************************************************/
  1077.  
  1078. void lsp_cex ()
  1079. {
  1080.     struct resbuf *rb,              /* result buffer to get input from
  1081.                                        AutoLISP */  
  1082.                   *rb1;             /* result buffer to compare input */
  1083.  
  1084.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1085.                                        as result buffer */
  1086.     rb1 = ads_buildlist(RTSHORT, 0, /* for handle number */
  1087.                         RTSTR, "",  /* for SQL statement */
  1088.                         NULL);
  1089.  
  1090.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1091.         testHandle(I(rb), COM_H) && /* whether handle number is right */
  1092.         asi_cex (hid[I(rb)].pt, S(rb->rbnext)) == ASI_GOOD)
  1093.                                     /* whether compilation and execution OK */
  1094.         ads_retint(1);              /* returns TRUE to AutoLISP */
  1095.     else                            /* compilation or execution failed */
  1096.         ads_retnil();               /* returns nil to AutoLISP */
  1097.  
  1098. }                                   /* end of lsp_cex () */
  1099.  
  1100. /****************************************************************************/
  1101. /*.doc lsp_fet (external) */
  1102. /*+
  1103.     Fetches forwards.
  1104. -*/
  1105. /****************************************************************************/
  1106.  
  1107. void
  1108. /*FCN*/lsp_fet ()
  1109. {
  1110.     struct resbuf *rb,              /* result buffer to get input from
  1111.                                        AutoLISP */  
  1112.                   *rb1;             /* result buffer to compare input */
  1113.  
  1114.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1115.                                        as result buffer */
  1116.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1117.  
  1118.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1119.         testHandle (I(rb), COM_H) &&/* whether handle number is right */
  1120.         asi_fet (hid[I(rb)].pt) == ASI_GOOD)
  1121.                                     /* whether fetch OK */
  1122.         ads_retint (1);             /* returns TRUE to AutoLISP */
  1123.     else                            /* fetch failed */
  1124.         ads_retnil();               /* returns nil to AutoLISP */
  1125.  
  1126. }                                   /* end of lsp_fet () */
  1127.  
  1128. /****************************************************************************/
  1129. /*.doc lsp_fbk (external) */
  1130. /*+
  1131.     Fetches backs.
  1132. -*/
  1133. /****************************************************************************/
  1134.  
  1135. void
  1136. /*FCN*/lsp_fbk ()
  1137. {
  1138.     struct resbuf *rb,              /* result buffer to get input from
  1139.                                        AutoLISP */  
  1140.                   *rb1;             /* result buffer to compare input */
  1141.  
  1142.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1143.                                        as result buffer */
  1144.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1145.  
  1146.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1147.         testHandle (I(rb) ,COM_H) &&/* whether handle number is right */
  1148.         asi_fbk (hid[I(rb)].pt) == ASI_GOOD)
  1149.                                     /* whether fetch OK */
  1150.         ads_retint (1);             /* returns TRUE to AutoLISP */
  1151.     else                            /* fetch failed */ 
  1152.         ads_retnil();               /* returns nil to AutoLISP */
  1153.  
  1154. }                                   /* end of lsp_fbk () */
  1155.  
  1156. /****************************************************************************/
  1157. /*.doc lsp_ftr (external) */
  1158. /*+
  1159.     Fetches top row.
  1160. -*/
  1161. /****************************************************************************/
  1162.  
  1163. void
  1164. /*FCN*/lsp_ftr ()
  1165. {
  1166.     struct resbuf *rb,              /* result buffer to get input from
  1167.                                        AutoLISP */  
  1168.                   *rb1;             /* result buffer to compare input */
  1169.  
  1170.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1171.                                        as result buffer */
  1172.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1173.  
  1174.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1175.         testHandle (I(rb) ,COM_H) &&/* whether handle number is right */
  1176.         asi_ftr (hid[I(rb)].pt) == ASI_GOOD)
  1177.                                     /* whether fetch OK */
  1178.         ads_retint (1);             /* returns TRUE to AutoLISP */
  1179.     else                            /* fetch failed */
  1180.         ads_retnil();               /* returns nil to AutoLISP */
  1181.  
  1182. }                                   /* end of lsp_ftr () */
  1183.  
  1184. /****************************************************************************/
  1185. /*.doc lsp_fbr (external) */
  1186. /*+
  1187.     Fetches bottom row.
  1188. -*/
  1189. /****************************************************************************/
  1190. void
  1191. /*FCN*/lsp_fbr ()
  1192. {
  1193.     struct resbuf *rb,              /* result buffer to get input from
  1194.                                        AutoLISP */  
  1195.                   *rb1;             /* result buffer to compare input */
  1196.  
  1197.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1198.                                        as result buffer */
  1199.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1200.  
  1201.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1202.         testHandle (I(rb) ,COM_H) &&/* whether handle number is right */
  1203.         asi_fbr (hid[I(rb)].pt) == ASI_GOOD)
  1204.                                     /* whether fetch OK */
  1205.         ads_retint (1);             /* returns TRUE to AutoLISP */
  1206.     else                            /* fetch failed */
  1207.         ads_retnil();               /* returns nil to AutoLISP */
  1208.  
  1209. }                                   /* end of lsp_fbr () */
  1210.  
  1211. /****************************************************************************/
  1212. /* .doc lsp_del (extrnal) */
  1213. /*+
  1214.     Delates current row.
  1215. -*/
  1216. /****************************************************************************/
  1217. void
  1218. /*FCN*/lsp_del ()
  1219. {
  1220.     struct resbuf *rb,              /* result buffer to get input from
  1221.                                        AutoLISP */  
  1222.                   *rb1;             /* result buffer to compare input */
  1223.  
  1224.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1225.                                        as result buffer */
  1226.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1227.  
  1228.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1229.         testHandle (I(rb) ,COM_H) &&/* whether handle number is right */
  1230.         asi_del (hid[I(rb)].pt) == ASI_GOOD)
  1231.                                     /* whether delate OK */
  1232.         ads_retint(1);              /* returns TRUE to AutoLISP */
  1233.     else                            /* delate failed */
  1234.         ads_retnil();               /* returns nil to AutoLISP */
  1235.  
  1236. }                                   /* end of lsp_del () */
  1237.  
  1238. /****************************************************************************/
  1239. /* .doc lsp_upd (extrnal) */
  1240. /*+
  1241.     Updates value in defined column at current row.
  1242. -*/
  1243. /****************************************************************************/
  1244.  
  1245. void
  1246. /*FCN*/lsp_upd ()
  1247. {
  1248.     struct resbuf *rb,              /* result buffer to get input from
  1249.                                        AutoLISP */  
  1250.                   *rb1;             /* result buffer to compare input */
  1251.     int           flag = ASI_BAD;   /* return value (ASI_BAD by default) */
  1252.     COLDSC        cd;               /* column description */
  1253.     ads_real      rbuff;            /* real buffer */
  1254.     integer       ibuff;            /* integer buffer */
  1255.  
  1256.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1257.                                        as result buffer */
  1258.     rb1 = ads_buildlist(RTSHORT, 0, /* for handle number */
  1259.                         RTSTR, "",  /* for column name */
  1260.                         RTSTR, "",  /* for new value or '\0' for NULL value */
  1261.                         NULL);
  1262.  
  1263.     if (rbcmp(rb, rb1) &&           /* wheter arguments are right */
  1264.         testHandle (I(rb) ,COM_H) &&/* whether handle number is right */
  1265.         findName (I(rb), &cd, S(rb->rbnext)))
  1266.                                     /* whether there is column with 
  1267.                                        defined name */
  1268.  
  1269.     if (*S(rb->rbnext->rbnext) == '\0')
  1270.                                     /* NULL value */
  1271.         flag = asi_upd (hid[I(rb)].pt, cd.colname, 0, NULL, "");
  1272.     else
  1273.         switch (cd.type) {
  1274.             case ASI_CHAR:          /* string value */
  1275.             flag = asi_upd (hid[I(rb)].pt, cd.colname, ASI_HCHAR,
  1276.                             S(rb->rbnext->rbnext), "");
  1277.             break;
  1278.  
  1279.             case ASI_DECIMAL:
  1280.             case ASI_INTEGER:
  1281.             case ASI_SMALLINT:      /* integer value */
  1282.             ibuff = atoi(S(rb->rbnext->rbnext));
  1283.             flag = asi_upd (hid[I(rb)].pt, cd.colname, ASI_HINT, &ibuff,
  1284.                             "");
  1285.             break;
  1286.  
  1287.             case ASI_NUMERIC:
  1288.             case ASI_FLOAT:
  1289.             case ASI_REAL:
  1290.             case ASI_DOUBLE:        /* double value */
  1291.             rbuff = atof(S(rb->rbnext->rbnext));
  1292.             flag = asi_upd (hid[I(rb)].pt, cd.colname, ASI_HREAL, &rbuff,
  1293.                             "");
  1294.         }
  1295.  
  1296.     if (flag == ASI_GOOD)           /* update OK */
  1297.         ads_retint(1);              /* returns TRUE to AutoLISP */
  1298.     else                            /* update failed */
  1299.         ads_retnil();               /* returns nil to AutoLISP */
  1300.  
  1301. }                                   /* end of lsp_upd () */
  1302.  
  1303. /****************************************************************************/
  1304. /*.doc lsp_currow (external) */
  1305. /*+
  1306.     Returns current row number to AutoLISP as RTLONG.
  1307. -*/
  1308. /****************************************************************************/
  1309. void
  1310. /*FCN*/lsp_currow ()
  1311. {
  1312.  
  1313.     struct resbuf *rb,              /* result buffer to get input from
  1314.                                        AutoLISP */  
  1315.                   *rb1;             /* result buffer to compare input */
  1316.  
  1317.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1318.                                        as result buffer */
  1319.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1320.  
  1321.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1322.         testHandle (I(rb) ,COM_H))  /* whether handle number is right */
  1323.         ads_retval(ads_buildlist(RTLONG, asi_currow (hid[I(rb)].pt), NULL));
  1324.                                     /* returns current row number to 
  1325.                                        AutoLISP */
  1326.     else 
  1327.         ads_retnil();               /* returns nil to AutoLISP */
  1328.  
  1329. }                                   /* end of lsp_currow */
  1330.  
  1331. /****************************************************************************/
  1332. /*.doc lsp_rowqty (external) */
  1333. /*+
  1334.     Returns total row number to AutoLISP as RTLONG.
  1335. -*/
  1336. /****************************************************************************/
  1337.  
  1338. void lsp_rowqty ()
  1339. {
  1340.     struct resbuf *rb,              /* result buffer to get input from
  1341.                                        AutoLISP */  
  1342.                   *rb1;             /* result buffer to compare input */
  1343.  
  1344.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1345.                                        as result buffer */
  1346.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1347.  
  1348.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1349.         testHandle (I(rb) ,COM_H))  /* whether handle number is right */
  1350.         ads_retval(ads_buildlist (RTLONG, asi_rowqty (hid[I(rb)].pt), NULL));
  1351.                                     /* Returns total row number to AutoLISP */
  1352.     else
  1353.         ads_retnil();               /* returns nil to AutoLISP */
  1354.  
  1355. }                                   /* end of lsp_rowqty */
  1356.  
  1357. /****************************************************************************/
  1358. /*.doc lsp_cds (external) */
  1359. /*+
  1360.     Returns column description as the result buffer to AutoLISP.
  1361. -*/
  1362. /****************************************************************************/
  1363. void
  1364. /*FCN*/lsp_cds ()
  1365. {
  1366.  
  1367.     struct resbuf *rb,              /* result buffer to get input from
  1368.                                        AutoLISP */  
  1369.                   *rb1;             /* result buffer to compare input */
  1370.  
  1371.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1372.                                        as result buffer */
  1373.     rb1 = ads_buildlist(RTSHORT, 0, /* for handle number */
  1374.                         RTSHORT, 0, /* for column number */
  1375.                         NULL);
  1376.  
  1377.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1378.         testHandle (I(rb) ,COM_H) &&/* whether handle number is right */
  1379.         (asi_stm (hid[I(rb)].pt) == ASI_CURSOR ||
  1380.          asi_stm (hid[I(rb)].pt) == ASI_UPDATE ||
  1381.          asi_stm (hid[I(rb)].pt) == ASI_DELETE ||
  1382.          asi_stm (hid[I(rb)].pt) == ASI_ALTER ||
  1383.          asi_stm (hid[I(rb)].pt) == ASI_INSERT) &&
  1384.                                     /* whether cursor operations */
  1385.         (rb1 = rbColDsc (I(rb), I(rb->rbnext))) != NULL)
  1386.         ads_retlist(rb1);           /* returns column description
  1387.                                        result buffer to AutoLISP */  
  1388.     else  ads_retnil();             /* returns nil to AutoLISP */
  1389.  
  1390. }                                   /* end of lsp_cds () */
  1391.  
  1392. /****************************************************************************/
  1393. /*.doc lsp_colsdsc (external) */
  1394. /*+
  1395.     Returns list of column descriptions as result buffer to AutoLISP.
  1396. -*/
  1397. /****************************************************************************/
  1398. void
  1399. /*FCN*/lsp_colsdsc ()
  1400. {
  1401.     short         i;                /* work index */
  1402.     struct resbuf *rb,              /* result buffer to get input from
  1403.                                        AutoLISP */  
  1404.                   *rb1,             /* result buffer to compare input */
  1405.                   *root,            /* work result buffers pointers */
  1406.                   *tail;
  1407.  
  1408.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1409.                                        as result buffer */
  1410.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1411.  
  1412.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1413.         testHandle (I(rb) ,COM_H) &&/* whether handle number is right */
  1414.         (asi_stm (hid[I(rb)].pt) == ASI_CURSOR ||
  1415.          asi_stm (hid[I(rb)].pt) == ASI_UPDATE ||
  1416.          asi_stm (hid[I(rb)].pt) == ASI_DELETE ||
  1417.          asi_stm (hid[I(rb)].pt) == ASI_ALTER ||
  1418.          asi_stm (hid[I(rb)].pt) == ASI_INSERT))
  1419.                                     /* whether cursor operations */
  1420.     for (root = NULL, i = 0; (rb1 = rbColDsc (I(rb), i)) != NULL; i++) {
  1421.                                     /* loop by all columns */
  1422.                    
  1423.         tail                    = ads_newrb (RTLB);
  1424.                                     /* open paren */
  1425.         tail->rbnext            = rb1;
  1426.                                     /* put current column description
  1427.                                        into result buffer */
  1428.         enttail(tail)->rbnext   = ads_newrb(RTLE);
  1429.                                     /* close paren */
  1430.         if (root == NULL)       root = tail;
  1431.                                     /* score root result buffer */
  1432.         else enttail(root)->rbnext = tail;
  1433.                                     /* put current result buffer to
  1434.                                        the tail */ 
  1435.     }
  1436.  
  1437.     if (root != NULL)      
  1438.         ads_retlist(root);          /* returns result buffer to AutoLISP */
  1439.     else              
  1440.         ads_retnil();               /* returns nil to AutoLISP */
  1441.  
  1442. }                                   /* end of lsp_coldsc () */
  1443.  
  1444. /****************************************************************************/
  1445. /*.doc lsp_cmt (external) */
  1446. /*+
  1447.     Saves changes into data base.
  1448. -*/
  1449. /****************************************************************************/
  1450. void
  1451. /*FCN*/lsp_cmt ()
  1452. {
  1453.     struct resbuf *rb,              /* result buffer to get input from
  1454.                                        AutoLISP */  
  1455.                   *rb1;             /* result buffer to compare input */
  1456.  
  1457.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1458.                                        as result buffer */
  1459.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1460.  
  1461.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1462.         testHandle (I(rb) ,COM_H) &&/* whether handle number is right */
  1463.         asi_cmt (hid[I(rb)].pt) == ASI_GOOD)
  1464.                                     /* whether save OK */
  1465.         ads_retint (1);             /* return TRUE to AutoLISP */
  1466.     else 
  1467.         ads_retnil();               /* returns nil to AutoLISP */
  1468.  
  1469. }                                   /* end of lsp_cmt () */
  1470.  
  1471. /****************************************************************************/
  1472. /*.doc lsp_rbk (external) */
  1473. /*+
  1474.     Rollback of all changes not yet commited to the data base.
  1475. -*/
  1476. /****************************************************************************/
  1477. void
  1478. /*FCN*/lsp_rbk ()
  1479. {
  1480.     struct resbuf *rb,              /* result buffer to get input from
  1481.                                        AutoLISP */  
  1482.                   *rb1;             /* result buffer to compare input */
  1483.  
  1484.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1485.                                        as result buffer */
  1486.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1487.  
  1488.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1489.         testHandle (I(rb) ,COM_H) &&/* whether handle number is right */
  1490.         asi_rbk (hid[I(rb)].pt) == ASI_GOOD)
  1491.                                     /* whether rollback OK */
  1492.         ads_retint (1);             /* returns TRUE to AutoLISP */
  1493.     else       
  1494.         ads_retnil();               /* returns nil to AutoLISP */
  1495.  
  1496. }                                   /* end of lsp_rbk () */
  1497.  
  1498. /****************************************************************************/
  1499. /*.doc lsp_cvl (external) */
  1500. /*+
  1501.     Returns value in defined column of current row to AutoLISP.
  1502. -*/
  1503. /****************************************************************************/
  1504. void
  1505. /*FCN*/lsp_cvl ()
  1506. {
  1507.     struct resbuf *rb,              /* result buffer to get input from
  1508.                                        AutoLISP */  
  1509.                   *rb1;             /* result buffer to compare input */
  1510.  
  1511.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1512.                                        as result buffer */
  1513.     rb1 = ads_buildlist(RTSHORT, 0, /* for handle number */
  1514.                         RTSHORT, 0, /* for column number */
  1515.                         NULL);
  1516.  
  1517.     ads_retnil();                   /* returns nil to AutoLISP by default */
  1518.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1519.         testHandle (I(rb), COM_H) &&/* whether handle number is right */
  1520.         (rb1 = getVal(I(rb), I(rb->rbnext))) != NULL)
  1521.                                     /* whether value gets OK */
  1522.         ads_retval(rb1);            /* returns value to AutoLISP */
  1523.  
  1524. }                                   /* end of lsp_cvl () */
  1525.  
  1526. /****************************************************************************/
  1527. /*.doc lsp_stm (external) */
  1528. /*+
  1529.     Returns type of last operation to AutoLISP.
  1530. -*/
  1531. /****************************************************************************/
  1532. void
  1533. /*FCN*/lsp_stm ()
  1534. {
  1535.     struct resbuf *rb,              /* result buffer to get input from
  1536.                                        AutoLISP */  
  1537.                   *rb1;             /* result buffer to compare input */
  1538.     char          state[10];
  1539.  
  1540.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1541.                                        as result buffer */
  1542.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1543.  
  1544.     *state          = '/0';
  1545.  
  1546.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1547.         testHandle (I(rb) ,COM_H))  /* whether handle number is right */
  1548.         switch (asi_stm (hid[I(rb)].pt)) {
  1549.  
  1550.         case ASI_DELETE:            /* delete statement */
  1551.             strcpy (state, "ASI_DELETE");
  1552.             break;
  1553.  
  1554.         case ASI_CREATE:            /* create statement */
  1555.             strcpy (state, "ASI_CREATE");
  1556.             break;
  1557.  
  1558.         case ASI_CURSOR:            /* cursor statement */
  1559.             strcpy (state, "ASI_CURSOR");
  1560.             break;
  1561.  
  1562.         case ASI_GRANT:             /* grant statement */
  1563.             strcpy (state, "ASI_GRANT");
  1564.             break;
  1565.  
  1566.         case ASI_REVOKE:            /* revoke statement */
  1567.             strcpy (state, "ASI_REVOKE");
  1568.             break;
  1569.  
  1570.         case ASI_INSERT:            /* insert statement */
  1571.             strcpy (state, "ASI_INSERT");
  1572.             break;
  1573.  
  1574.         case ASI_DROP:              /* drop statement */
  1575.             strcpy (state, "ASI_DROP");
  1576.             break;
  1577.  
  1578.         case ASI_UPDATE:            /* update statement */
  1579.             strcpy (state, "ASI_UPDATE");
  1580.             break;
  1581.  
  1582.         case ASI_ALTER:             /* alter statement */
  1583.             strcpy (state, "ASI_ALTER");
  1584.         }
  1585.  
  1586.     if (*state == '\0')        
  1587.         ads_retnil();               /* returns nil to AutoLISP */
  1588.     else                    
  1589.         ads_retstr(state);          /* returns state to AutoLISP */
  1590.  
  1591. }                                   /* end of lsp_stm () */
  1592.  
  1593.  
  1594. /****************************************************************************/
  1595. /*.doc lsp_opr (external) */
  1596. /*+
  1597.     Returns type of last operation to AutoLISP.
  1598. -*/
  1599. /****************************************************************************/
  1600. void
  1601. /*FCN*/lsp_opr ()
  1602. {
  1603.     struct resbuf *rb,              /* result buffer to get input from
  1604.                                        AutoLISP */  
  1605.                   *rb1;             /* result buffer to compare input */
  1606.     char          state[10];
  1607.  
  1608.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1609.                                        as result buffer */
  1610.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1611.  
  1612.     *state = '/0';
  1613.  
  1614.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1615.         testHandle (I(rb) ,COM_H))  /* whether handle number is right */
  1616.         switch (asi_opr (hid[I(rb)].pt)) {
  1617.  
  1618.         case ASI_COM:               /* compile operation */
  1619.             strcpy (state, "ASI_COM");
  1620.             break;
  1621.  
  1622.         case ASI_EXE:               /* execute operation */
  1623.             strcpy (state, "ASI_EXE");
  1624.             break;
  1625.  
  1626.         case ASI_DEL:               /* delete operation */
  1627.             strcpy (state, "ASI_DEL");
  1628.             break;
  1629.  
  1630.         case ASI_FET:               /* fetch forward operation */
  1631.             strcpy (state, "ASI_FET");
  1632.             break;
  1633.  
  1634.         case ASI_FBK:               /* fetch backward operation */
  1635.             strcpy (state, "ASI_FBK");
  1636.             break;
  1637.  
  1638.         case ASI_UPD:               /* update operation */
  1639.             strcpy (state, "ASI_UPD");
  1640.             break;
  1641.  
  1642.         case ASI_CMT:               /* commit operation */
  1643.             strcpy (state, "ASI_CMT");
  1644.             break;
  1645.  
  1646.         case ASI_RBK:               /* roll back changes operation */
  1647.             strcpy (state, "ASI_RBK");
  1648.             break;
  1649.  
  1650.         case ASI_FFR:               /* fetch top operation */
  1651.             strcpy (state, "ASI_FFR");
  1652.             break;
  1653.  
  1654.         case ASI_FLR:               /* fetch bottom operation */
  1655.             strcpy (state, "ASI_FLR");
  1656.         }
  1657.  
  1658.     if (*state == '\0')  
  1659.         ads_retnil();               /* returns nil to AutoLISP */
  1660.     else             
  1661.         ads_retstr(state);          /* returns operation name to AutoLISP */
  1662.  
  1663. }                                   /* end of lsp_opr () */
  1664.  
  1665. /****************************************************************************/
  1666. /*.doc lsp_err (external) */
  1667. /*+
  1668.     Returns error position in SQL statement to AutoLISP.
  1669. -*/
  1670. /****************************************************************************/
  1671. void
  1672. /*FCN*/lsp_err ()
  1673. {
  1674.     struct resbuf *rb,              /* result buffer to get input from
  1675.                                        AutoLISP */  
  1676.                   *rb1;             /* result buffer to compare input */
  1677.  
  1678.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1679.                                        as result buffer */
  1680.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1681.  
  1682.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1683.         testHandlNumb (I(rb)))      /* whether handle number is right */
  1684.         ads_retint (asi_err (hid[I(rb)].pt));
  1685.                                     /* returns error position in SQL
  1686.                                        statement to AutoLISP */
  1687.     else    
  1688.         ads_retnil();               /* returns nil to AutoLISP */
  1689.  
  1690. }                                   /* end of lsp_err () */
  1691.  
  1692. /****************************************************************************/
  1693. /*.doc lsp_errmsg (external) */
  1694. /*+
  1695.     Returns error message to AutoLISP.
  1696. -*/
  1697. /****************************************************************************/
  1698. void
  1699. /*FCN*/lsp_errmsg ()
  1700. {
  1701.     struct resbuf *rb,              /* result buffer to get input from
  1702.                                        AutoLISP */  
  1703.                   *rb1;             /* result buffer to compare input */
  1704.  
  1705.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1706.                                        as result buffer */
  1707.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1708.  
  1709.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1710.         testHandlNumb (I(rb)))      /* whether handle number is right */
  1711.         ads_retstr (asi_errmsg (hid[I(rb)].pt));
  1712.                                     /* returns error messge to AutoLISP */
  1713.     else
  1714.         ads_retnil();               /* returns nil to AutoLISP */
  1715.  
  1716. }                                   /* end of lsp_errmsg () */
  1717.  
  1718. /****************************************************************************/
  1719. /*.doc lsp_grow () */
  1720. /*+
  1721.     Returns current row values to AutoLISP as result buffers.
  1722. -*/
  1723. /****************************************************************************/
  1724. void
  1725. /*FCN*/lsp_grow ()
  1726. {
  1727.     struct resbuf *rb,              /* result buffer to get input from
  1728.                                        AutoLISP */  
  1729.                   *rb1;             /* result buffer to compare input */
  1730.  
  1731.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1732.                                        as result buffer */
  1733.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1734.  
  1735.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1736.         testHandle (I(rb), COM_H) &&/* whether handle number is right */
  1737.         (asi_stm (hid[I(rb)].pt) == ASI_CURSOR ||
  1738.          asi_stm (hid[I(rb)].pt) == ASI_UPDATE ||
  1739.          asi_stm (hid[I(rb)].pt) == ASI_DELETE ||
  1740.          asi_stm (hid[I(rb)].pt) == ASI_ALTER ||
  1741.          asi_stm (hid[I(rb)].pt) == ASI_INSERT) &&
  1742.                                     /* whether cursor operation */
  1743.         (rb1 = getRowVal(I(rb))) != NULL)
  1744.                                     /* whether gets values OK */
  1745.         ads_retlist(rb1);           /* returns current row values to AutoLISP
  1746.                                        as result buffers */
  1747.     else 
  1748.         ads_retnil();               /* returns nil to AutoLISP */
  1749.  
  1750. }                                   /* end of lsp_grow () */
  1751.  
  1752. /****************************************************************************/
  1753. /*.doc lsp_gettable () */
  1754. /*+
  1755.     Returns values of current cursor to AutoLISP.
  1756. -*/
  1757. /****************************************************************************/
  1758. void
  1759. /*FCN*/lsp_gettable ()
  1760. {
  1761.     struct resbuf *rb,              /* result buffer to get input from
  1762.                                        AutoLISP */  
  1763.                   *rb1,             /* result buffer to compare input */
  1764.                   *root = NULL,     /* work result buffers */
  1765.                   *tail;
  1766.  
  1767.     rb = ads_getargs();             /* gets arguments from AutoLISP
  1768.                                        as result buffer */
  1769.     rb1 = ads_newrb (RTSHORT);      /* for handle number */
  1770.  
  1771.     if (rbcmp (rb, rb1) &&          /* wheter arguments are right */
  1772.         testHandle (I(rb), COM_H) &&/* whether handle number is right */
  1773.         (asi_stm (hid[I(rb)].pt) == ASI_CURSOR ||
  1774.          asi_stm (hid[I(rb)].pt) == ASI_UPDATE ||
  1775.          asi_stm (hid[I(rb)].pt) == ASI_DELETE ||
  1776.          asi_stm (hid[I(rb)].pt) == ASI_ALTER ||
  1777.          asi_stm (hid[I(rb)].pt) == ASI_INSERT) &&
  1778.                                     /* whether cursor operation */
  1779.         asi_ftr (hid[I(rb)].pt) == ASI_GOOD)
  1780.                                     /* whether fetch top OK */
  1781.  
  1782.     do                              /* loop by all rows */
  1783.     if ((rb1 = getRowVal(I(rb))) != NULL) {
  1784.                                     /* get current row values */
  1785.         tail                    = ads_newrb (RTLB);
  1786.                                     /* open paren */
  1787.         tail->rbnext            = rb1;
  1788.                                     /* put current row buffer to list */
  1789.         enttail(tail)->rbnext   = ads_newrb(RTLE);
  1790.                                     /* close paren */
  1791.         if (root == NULL)       root = tail;
  1792.                                     /* score pointer to root group */
  1793.         else enttail(root)->rbnext  
  1794.                                 = tail;
  1795.                                 /* put next geroup to the tail of list */
  1796.     }
  1797.     while (asi_fet(hid[I(rb)].pt) == ASI_GOOD);
  1798.  
  1799.     if (root != NULL)       
  1800.         ads_retlist(root);          /* returns list to AutoLISP */
  1801.     else                    
  1802.         ads_retnil();               /* returns nil to AutoLISP */
  1803.  
  1804. }                                   /* end of lsp_gettable () */
  1805. /*EOF*/
  1806.  
  1807.